using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using RTMP.SimpleClient.Exceptions;
using RTMP.SimpleClient.Messages;

namespace RTMP.SimpleClient.Callbacks
{
    /// <summary>
    /// 回调管理器，负责管理和调用消息回调
    /// </summary>
    public class CallbackManager
    {
        private readonly ConcurrentDictionary<CallbackKey, CallbackRegistration> _callbacks = new();
        private readonly IMessageConverter _messageConverter;

        public CallbackManager(IMessageConverter messageConverter)
        {
            _messageConverter = messageConverter ?? throw new ArgumentNullException(nameof(messageConverter));
        }

        /// <summary>
        /// 注册强类型消息回调
        /// </summary>
        /// <typeparam name="T">消息类型</typeparam>
        /// <param name="key">回调键</param>
        /// <param name="callback">回调处理器</param>
        /// <param name="isOneTime">是否为一次性回调</param>
        /// <param name="timeout">超时时间</param>
        public void RegisterCallback<T>(CallbackKey key, IMessageCallback<T> callback, bool isOneTime = false, TimeSpan? timeout = null)
            where T : class
        {
            var registration = new CallbackRegistration
            {
                Key = key,
                Handler = callback,
                MessageType = typeof(T),
                IsOneTime = isOneTime,
                Timeout = timeout
            };

            _callbacks.AddOrUpdate(key, registration, (_, _) => registration);
        }

        /// <summary>
        /// 注册委托形式的回调
        /// </summary>
        /// <typeparam name="T">消息类型</typeparam>
        /// <param name="key">回调键</param>
        /// <param name="handler">处理委托</param>
        /// <param name="isOneTime">是否为一次性回调</param>
        /// <param name="timeout">超时时间</param>
        public void RegisterCallback<T>(CallbackKey key, Func<T, CancellationToken, Task> handler, bool isOneTime = false, TimeSpan? timeout = null)
            where T : class
        {
            var callback = new DelegateMessageCallback<T>(handler);
            RegisterCallback(key, callback, isOneTime, timeout);
        }

        /// <summary>
        /// 注册简单委托形式的回调
        /// </summary>
        /// <typeparam name="T">消息类型</typeparam>
        /// <param name="key">回调键</param>
        /// <param name="handler">处理委托</param>
        /// <param name="isOneTime">是否为一次性回调</param>
        /// <param name="timeout">超时时间</param>
        public void RegisterCallback<T>(CallbackKey key, Action<T> handler, bool isOneTime = false, TimeSpan? timeout = null)
            where T : class
        {
            var callback = new DelegateMessageCallback<T>(handler);
            RegisterCallback(key, callback, isOneTime, timeout);
        }

        /// <summary>
        /// 取消注册回调
        /// </summary>
        /// <param name="key">回调键</param>
        /// <returns>是否成功取消</returns>
        public bool UnregisterCallback(CallbackKey key)
        {
            return _callbacks.TryRemove(key, out _);
        }

        /// <summary>
        /// 清除所有回调
        /// </summary>
        public void ClearCallbacks()
        {
            _callbacks.Clear();
        }

        /// <summary>
        /// 处理接收到的消息
        /// </summary>
        /// <param name="rawMessage">原始消息数据</param>
        /// <param name="actionId">动作ID</param>
        /// <param name="streamId">流ID</param>
        /// <param name="commandName">命令名称</param>
        /// <param name="cancellationToken">取消令牌</param>
        public async Task ProcessMessageAsync(byte[] rawMessage, double actionId, uint streamId, string? commandName = null, CancellationToken cancellationToken = default)
        {
            // 尝试匹配回调键（按优先级顺序）
            var possibleKeys = new[]
            {
                new CallbackKey(actionId, streamId, commandName), // 精确匹配
                new CallbackKey(actionId, streamId),              // ActionId + StreamId
                new CallbackKey(actionId, 0, commandName),        // ActionId + CommandName
                new CallbackKey(0, streamId, commandName),        // StreamId + CommandName
                CallbackKey.FromTransactionId(actionId),               // 仅ActionId
                CallbackKey.FromStreamId(streamId),               // 仅StreamId
                CallbackKey.FromCommand(commandName ?? string.Empty) // 仅CommandName
            };

            CallbackRegistration? matchedRegistration = null;
            CallbackKey matchedKey = default;

            foreach (var key in possibleKeys)
            {
                if (_callbacks.TryGetValue(key, out var registration))
                {
                    matchedRegistration = registration;
                    matchedKey = key;
                    break;
                }
            }

            if (matchedRegistration == null)
            {
                // 没有找到匹配的回调，丢弃消息
                return;
            }

            try
            {
                // 将原始消息转换为强类型对象
                var convertedMessage = await _messageConverter.ConvertAsync(rawMessage, matchedRegistration.MessageType, cancellationToken);

                if (convertedMessage == null)
                {
                    Console.WriteLine($"消息转换失败: 无法将原始数据转换为 {matchedRegistration.MessageType.Name}");
                    return;
                }

                // 调用回调处理器
                await InvokeCallbackAsync(matchedRegistration.Handler, convertedMessage, cancellationToken);

                // 如果是一次性回调，移除注册
                if (matchedRegistration.IsOneTime)
                {
                    _callbacks.TryRemove(matchedKey, out _);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"回调处理时发生错误 (Key: {matchedKey}): {ex.Message}");

                // 对于一次性回调，即使出错也要移除
                if (matchedRegistration.IsOneTime)
                {
                    _callbacks.TryRemove(matchedKey, out _);
                }
            }
        }

        /// <summary>
        /// 调用回调处理器
        /// </summary>
        private async Task InvokeCallbackAsync(object handler, object message, CancellationToken cancellationToken)
        {
            // 使用反射调用泛型回调方法
            var handlerType = handler.GetType();
            var handleMethod = handlerType.GetMethod("HandleAsync");

            if (handleMethod != null)
            {
                var result = handleMethod.Invoke(handler, new[] { message, cancellationToken });
                if (result is Task task)
                {
                    await task;
                }
            }
            else
            {
                throw new RTMPException($"无法找到回调处理器的HandleAsync方法: {handlerType.Name}");
            }
        }

        /// <summary>
        /// 清理过期的回调
        /// </summary>
        public void CleanupExpiredCallbacks()
        {
            var now = DateTime.UtcNow;
            var keysToRemove = new List<CallbackKey>();

            foreach (var kvp in _callbacks)
            {
                var registration = kvp.Value;
                if (registration.Timeout.HasValue &&
                    now - registration.RegisteredAt > registration.Timeout.Value)
                {
                    keysToRemove.Add(kvp.Key);
                }
            }

            foreach (var key in keysToRemove)
            {
                _callbacks.TryRemove(key, out _);
            }
        }

        /// <summary>
        /// 获取当前注册的回调数量
        /// </summary>
        public int CallbackCount => _callbacks.Count;
    }
}